package org.sqldroid;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.Statement;

import android.database.Cursor;
import android.util.Log;

public class SqldroidStatement implements Statement {

	private SQLiteDatabase db;
	private SqldroidConnection sqldroidConnection;
	private SqldroidResultSet rs = null;
	private Integer maxRows = null;

	public SqldroidStatement(final SqldroidConnection sqldroid) {
		sqldroidConnection = sqldroid;
		db = sqldroid.getDb();
	}

	public void addBatch(final String sql) throws SQLException {
		System.err.println(" ********************* not implemented @ " + DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());

	}

	public void cancel() throws SQLException {
		System.err.println(" ********************* not implemented @ " + DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());

	}

	public void clearBatch() throws SQLException {
		System.err.println(" ********************* not implemented @ " + DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());

	}

	public void clearWarnings() throws SQLException {
		System.err.println(" ********************* not implemented @ " + DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());

	}

	public void close() throws SQLException {
		closeResultSet();
		sqldroidConnection = null;
		db = null;
	}

	private void closeResultSet() throws SQLException {
		if (rs != null) {
			rs.close();
			rs = null;
		}
	}

	public boolean execute(final String sql) throws SQLException {
		boolean ok = false;
		closeResultSet();
		try {
			final boolean isSelect = sql.toUpperCase().matches("(?m)(?s)\\s*SELECT.*");
			if (isSelect) {
				final String limitedSql = sql + (maxRows != null ? " LIMIT " + maxRows : "");
				rs = new SqldroidResultSet(db.rawQuery(limitedSql, new String[0]));
			} else {
				db.execSQL(sql);
			}
			ok = true;

			final boolean resultSetAvailable = ok && !sql.toUpperCase().startsWith("CREATE") && rs != null
					&& rs.getMetaData().getColumnCount() != 0;

			if (resultSetAvailable) {
				boolean headerDrawn = false;
				while (rs.next()) {
					if (!headerDrawn) {
						Log.d("SqlDroid", sql);
						for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++) {
							System.out.print(" | ");
							System.out.print(rs.getMetaData().getColumnLabel(i));
						}
						System.out.println(" | ");
						headerDrawn = true;
					}
					for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++) {
						System.out.print(" | ");
						System.out.print(rs.getString(i));
					}
					System.out.println(" | ");
				}
				rs.beforeFirst();
			}

			return resultSetAvailable;
		} catch (final android.database.SQLException e) {
			Log.e("Sqldroid", "SQLException: '" + e.getClass().getName() + "' '" + e.getMessage() + "'");
			e.printStackTrace();
			throw e;
		} catch (final java.lang.RuntimeException e) {
			Log.e("Sqldroid", "RuntimeException: '" + e.getClass().getName() + "' '" + e.getMessage() + "'");
			e.printStackTrace();
			throw e;
		} catch (final Error e) {
			Log.e("Sqldroid", "Error: '" + e.getClass().getName() + "' '" + e.getMessage() + "'");
			e.printStackTrace();
			throw e;
		}
	}

	public boolean execute(final String sql, final int autoGeneratedKeys) throws SQLException {
		System.err.println(" ********************* not implemented @ " + DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());

		return false;
	}

	public boolean execute(final String sql, final int[] columnIndexes) throws SQLException {
		System.err.println(" ********************* not implemented @ " + DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());

		return false;
	}

	public boolean execute(final String sql, final String[] columnNames) throws SQLException {
		System.err.println(" ********************* not implemented @ " + DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());

		return false;
	}

	public int[] executeBatch() throws SQLException {
		System.err.println(" ********************* not implemented @ " + DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());
		return null;
	}

	public ResultSet executeQuery(final String sql) throws SQLException {
		closeResultSet();
		final Cursor c = db.rawQuery(sql, null);
		rs = new SqldroidResultSet(c);
		return rs;
	}

	public int executeUpdate(final String sql) throws SQLException {
		closeResultSet();
		db.execSQL(sql);
		return 0;
	}

	public int executeUpdate(final String sql, final int autoGeneratedKeys) throws SQLException {
		System.err.println(" ********************* not implemented @ " + DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());
		return 0;
	}

	public int executeUpdate(final String sql, final int[] columnIndexes) throws SQLException {
		System.err.println(" ********************* not implemented @ " + DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());
		return 0;
	}

	public int executeUpdate(final String sql, final String[] columnNames) throws SQLException {
		System.err.println(" ********************* not implemented @ " + DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());
		return 0;
	}

	public Connection getConnection() throws SQLException {
		return sqldroidConnection;
	}

	public int getFetchDirection() throws SQLException {
		System.err.println(" ********************* not implemented @ " + DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());
		return 0;
	}

	public int getFetchSize() throws SQLException {
		System.err.println(" ********************* not implemented @ " + DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());
		return 0;
	}

	public ResultSet getGeneratedKeys() throws SQLException {
		System.err.println(" ********************* not implemented @ " + DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());
		return null;
	}

	public int getMaxFieldSize() throws SQLException {
		System.err.println(" ********************* not implemented @ " + DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());
		return 0;
	}

	public int getMaxRows() throws SQLException {
		System.err.println(" ********************* not implemented @ " + DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());
		return 0;
	}

	public boolean getMoreResults() throws SQLException {
		return getMoreResults(CLOSE_CURRENT_RESULT);
	}

	public boolean getMoreResults(final int current) throws SQLException {
		closeResultSet();
		return false;
	}

	public int getQueryTimeout() throws SQLException {
		System.err.println(" ********************* not implemented @ " + DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());
		return 0;
	}

	public ResultSet getResultSet() throws SQLException {
		return rs;
	}

	public int getResultSetConcurrency() throws SQLException {
		System.err.println(" ********************* not implemented @ " + DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());
		return 0;
	}

	public int getResultSetHoldability() throws SQLException {
		System.err.println(" ********************* not implemented @ " + DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());
		return 0;
	}

	public int getResultSetType() throws SQLException {
		System.err.println(" ********************* not implemented @ " + DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());
		return 0;
	}

	public int getUpdateCount() throws SQLException {
		System.err.println(" ********************* not implemented @ " + DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());
		return 0;
	}

	public SQLWarning getWarnings() throws SQLException {
		System.err.println(" ********************* not implemented @ " + DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());
		return null;
	}

	public void setCursorName(final String name) throws SQLException {
		System.err.println(" ********************* not implemented @ " + DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());

	}

	public void setEscapeProcessing(final boolean enable) throws SQLException {
		System.err.println(" ********************* not implemented @ " + DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());

	}

	public void setFetchDirection(final int direction) throws SQLException {
		System.err.println(" ********************* not implemented @ " + DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());

	}

	public void setFetchSize(final int rows) throws SQLException {
		System.err.println(" ********************* not implemented @ " + DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());
	}

	public void setMaxFieldSize(final int max) throws SQLException {
		System.err.println(" ********************* not implemented @ " + DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());
	}

	public void setMaxRows(final int max) throws SQLException {
		if (isClosed()) {
			throw new SQLException("Statement is closed.");
		} else if (max < 0) {
			throw new SQLException("Max rows must be zero or positive. Got " + max);
		} else if (max == 0) {
			maxRows = null;
		} else {
			maxRows = max;
		}
	}

	public void setQueryTimeout(final int seconds) throws SQLException {
		System.err.println(" ********************* not implemented @ " + DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());
	}

	public boolean isWrapperFor(final Class<?> arg0) throws SQLException {
		System.err.println(" ********************* not implemented @ " + DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());
		return false;
	}

	public <T> T unwrap(final Class<T> arg0) throws SQLException {
		System.err.println(" ********************* not implemented @ " + DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());
		return null;
	}

	public boolean isClosed() throws SQLException {
		return sqldroidConnection == null;
	}

	public boolean isPoolable() throws SQLException {
		System.err.println(" ********************* not implemented @ " + DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());
		return false;
	}

	public void setPoolable(final boolean poolable) throws SQLException {
		System.err.println(" ********************* not implemented @ " + DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());

	}

}
